package cn.vehicle.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.vehicle.domains.bo.QueryPermissionBo;
import cn.vehicle.domains.bo.QueryRoleBo;
import cn.vehicle.domains.bo.QueryUserBo;
import cn.vehicle.domains.entity.SysPermissionEntity;
import cn.vehicle.domains.entity.SysRoleEntity;
import cn.vehicle.domains.entity.SysUserEntity;
import cn.vehicle.domains.info.UserInfo;
import cn.vehicle.exception.VehicleAccessException;
import cn.vehicle.mapper.SysRolePermissionMapper;
import cn.vehicle.mapper.SysUserMapper;
import cn.vehicle.mapper.SysUserRoleMapper;
import cn.vehicle.service.SysPermissionService;
import cn.vehicle.service.SysRoleService;
import cn.vehicle.service.SysUserService;
import jakarta.annotation.Resource;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 系统用户服务实现类
 * <p>
 * 负责系统用户的持久化操作，包括用户的新增、修改、删除、查询及角色权限加载。
 * 通过 {@link SysUserMapper}、{@link SysUserRoleMapper}、{@link SysRoleService} 和 {@link SysPermissionService}
 * 实现用户数据与角色权限的综合管理，是系统用户管理模块的核心服务层。
 * </p>
 *
 * <p>主要职责：</p>
 * <ul>
 *   <li>封装用户表（sys_user）的基础增删改查逻辑；</li>
 *   <li>实现用户与角色、权限之间的关联查询；</li>
 *   <li>捕获数据库异常并转换为业务异常 {@link VehicleAccessException}。</li>
 * </ul>
 */
@Service
public class SysUserServiceImpl implements SysUserService {

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private SysUserRoleMapper sysUserRoleMapper;

    @Resource
    private SysRoleService sysRoleService;

    @Resource
    private SysRolePermissionMapper sysRolePermissionMapper;

    @Resource
    private SysPermissionService sysPermissionService;

    /**
     * 新增用户
     *
     * @param sysUserEntity 用户实体对象
     * @throws VehicleAccessException 当用户已存在（唯一约束冲突）时抛出
     */
    public void addUser(SysUserEntity sysUserEntity) {
        try {
            // 插入用户信息到数据库
            sysUserMapper.insertUser(sysUserEntity);
        } catch (DuplicateKeyException e) {
            // 捕获数据库唯一约束异常并转化为业务异常
            throw VehicleAccessException.DATE_EXIST.newInstance("用户已存在");
        }
    }

    /**
     * 根据ID查询用户信息
     *
     * @param id 用户主键ID
     * @return 用户实体对象
     */
    @Override
    public SysUserEntity getUserById(Long id) {
        return sysUserMapper.selectUserById(id);
    }

    /**
     * 更新用户信息
     *
     * @param updateEntity 更新后的用户实体对象
     * @throws VehicleAccessException 若更新失败（未更新到记录）则抛出异常
     */
    @Override
    public void updateUser(SysUserEntity updateEntity) {
        // 执行更新操作
        int i = sysUserMapper.updateUser(updateEntity);
        // 若未更新任何记录，说明用户不存在
        if (i != 1) {
            throw VehicleAccessException.DATE_NOT_EXIST.newInstance("更新用户未更新到数据");
        }
    }

    /**
     * 删除用户
     *
     * @param id 用户主键ID
     * @throws VehicleAccessException 若删除失败（未删除到记录）则抛出异常
     */
    @Override
    public void deleteUser(Long id) {
        // 执行用户删除操作
        int i = sysUserMapper.deleteUserById(id);
        // 若删除数量不为1，说明用户不存在或已被删除
        if (i != 1) {
            throw VehicleAccessException.DATE_NOT_EXIST.newInstance("删除用户未更新到数据");
        }
    }

    /**
     * 查询用户列表
     *
     * @param queryUserBo 查询条件封装对象
     * @return 用户实体列表
     */
    @Override
    public List<SysUserEntity> selectUserList(QueryUserBo queryUserBo) {
        return sysUserMapper.selectUserList(queryUserBo);
    }

    /**
     * 根据用户名查询用户信息
     *
     * @param username 用户名
     * @return 用户实体对象
     */
    @Override
    public SysUserEntity getUserByUsername(String username) {
        return sysUserMapper.selectUserByUsername(username);
    }

    /**
     * 查询用户的角色与权限信息
     *
     * <p>根据用户ID，先查询角色列表，再根据角色ID集合查询对应权限。</p>
     *
     * @param userId 用户主键ID
     * @return 用户信息对象，包含角色与权限列表
     */
    @Override
    public UserInfo getUserRoleAndPermission(Long userId) {
        // 创建用户信息对象，用于封装角色与权限数据
        UserInfo userInfo = new UserInfo();
        // 查询用户绑定的角色ID集合
        List<Long> roleIds = sysUserRoleMapper.selectRoleIdsByUserId(userId);
        // 若用户未绑定任何角色，则直接返回空的用户信息对象
        if (CollectionUtil.isEmpty(roleIds)) {
            return userInfo;
        }

        // 封装角色查询条件，批量查询用户的角色信息
        QueryRoleBo queryRoleBo = new QueryRoleBo();
        queryRoleBo.setIds(roleIds);
        // 查询角色实体列表并设置到用户信息中
        List<SysRoleEntity> sysRoleEntityList = sysRoleService.selectRoleList(queryRoleBo);
        userInfo.setRoleEntityList(sysRoleEntityList);

        // 查询这些角色所拥有的权限ID集合
        List<Long> permissionIds = sysRolePermissionMapper.selectPermissionIdsByRoleId(roleIds);

        // 去重，防止重复权限
        permissionIds = permissionIds.stream().distinct().toList();

        // 若角色未绑定任何权限，则直接返回用户信息
        if (CollectionUtil.isEmpty(permissionIds)) {
            return userInfo;
        }

        // 封装权限查询条件并执行查询
        QueryPermissionBo queryPermissionBo = new QueryPermissionBo();
        queryPermissionBo.setIds(permissionIds);
        List<SysPermissionEntity> selectPermissionList = sysPermissionService.selectPermissionList(queryPermissionBo);
        // 将查询到的权限列表设置到用户信息对象中
        userInfo.setPermissionEntityList(selectPermissionList);
        return userInfo;

    }
}
